package cn.vcjf.weapp.common.util;

import javax.crypto.Cipher;
import java.io.*;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;


public class RASUtils {


    public static byte[] encrypt(byte[] plainBytes, PublicKey publicKey, int keyLength, int reserveSize, String cipherAlgorithm) throws Exception {
        int keyByteSize = keyLength / 8;
        int encryptBlockSize = keyByteSize - reserveSize;
        int nBlock = plainBytes.length / encryptBlockSize;
        if ((plainBytes.length % encryptBlockSize) != 0) {
            nBlock += 1;
        }
        ByteArrayOutputStream outbuf = null;
        try {
            Cipher cipher = Cipher.getInstance(cipherAlgorithm);
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);

            outbuf = new ByteArrayOutputStream(nBlock * keyByteSize);
            for (int offset = 0; offset < plainBytes.length; offset += encryptBlockSize) {
                int inputLen = plainBytes.length - offset;
                if (inputLen > encryptBlockSize) {
                    inputLen = encryptBlockSize;
                }
                byte[] encryptedBlock = cipher.doFinal(plainBytes, offset, inputLen);
                outbuf.write(encryptedBlock);
            }
            outbuf.flush();
            return outbuf.toByteArray();
        } catch (Exception e) {
            throw new Exception("ENCRYPT ERROR:", e);
        } finally {
            try{
                if(outbuf != null){
                    outbuf.close();
                }
            }catch (Exception e){
                outbuf = null;
                throw new Exception("CLOSE ByteArrayOutputStream ERROR:", e);
            }
        }
    }

    public static PublicKey getPubKey(String publicKeyPath,String keyAlgorithm){
        PublicKey publicKey = null;
        InputStream inputStream = null;
        try
        {
            System.out.println("getPubkey 1......");
            inputStream = new FileInputStream(publicKeyPath);
            System.out.println("getPubkey 2......");
            publicKey = getPublicKey(inputStream,keyAlgorithm);
            System.out.println("getPubkey 3......");

        } catch (Exception e) {

            e.printStackTrace();//EAD PUBLIC KEY ERROR
            System.out.println("加载公钥出错!");
        } finally {
            if (inputStream != null){
                try {
                    inputStream.close();
                }catch (Exception e){
                    System.out.println("加载公钥,关闭流时出错!");
                }
            }
        }
        return publicKey;
    }

    public static PublicKey getPublicKey(InputStream inputStream, String keyAlgorithm) throws Exception {
        try
        {
            BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
            StringBuilder sb = new StringBuilder();
            String readLine = null;
            while ((readLine = br.readLine()) != null) {
                if (readLine.charAt(0) == '-') {
                    continue;
                } else {
                    sb.append(readLine);
                    sb.append('\r');
                }
            }
            X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(Encodes.decodeBase64(sb.toString()));
            KeyFactory keyFactory = KeyFactory.getInstance(keyAlgorithm);
            //下行出错  java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: DerInputStream.getLength(): lengthTag=127, too big.
            PublicKey publicKey = keyFactory.generatePublic(pubX509);
            System.out.println("b7.........");
            return publicKey;
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("b8.........");
            throw new Exception("READ PUBLIC KEY ERROR:", e);
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                inputStream = null;
                throw new Exception("INPUT STREAM CLOSE ERROR:", e);
            }
        }
    }


//    public static void main(String[] args) {
//        try {
//            String name = "测试账户";
//            String keyFilePath = "F:/mykey/jar/public.pem";
//            PublicKey pub=getPubKey(keyFilePath,"RSA");
//            //rsa是微信付款到银行卡要求我们填充的字符串
//            String rsa ="RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING";
//            //进行加密
//            byte[] estr = encrypt(name.getBytes(),pub,2048, 11,rsa);
//            String encBankAcctName =Encodes.encodeBase62(estr);//并转为base64格式
//            //测试输出
//            System.out.println(encBankAcctName);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }


//        String url ="https://fraud.mch.weixin.qq.com/risk/getpublickey";
//        String certPath = "F:/mykey/jar/apiclient_cert.p12";
//        String nonceStr =CardRequestUtils.genCodes(8);
//
//
//        //构建签名参数
//        Map<String, String> requestMap = new HashMap<String, String>();
//        requestMap.put("mch_id","1487329042");
//        requestMap.put("nonce_str",nonceStr);
//        String sign = CardRequestUtils.getSign(requestMap,"qcsgOCj6ayIdEHUU5WeGvnqV13SgFmPv").toUpperCase();
//
//        String xml = "<xml>" +
//                "<mch_id>1487329042</mch_id>" +
//                "<nonce_str>"+nonceStr+"</nonce_str>" +
//                "<sign>"+sign+"</sign>" +
//                "</xml>";
//        String resultXml = HttpClientTools.httpPostSendReceiveAndCert(url,xml.toString(), "1487329042",certPath);
//        System.out.println(resultXml);
//    }


}
